﻿using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System.Xml;

namespace XieCan.Core
{
  /// <summary>
  /// JSON操作扩展类
  /// </summary>
  public static class NewtonsoftJsonEx
  {
    /// <summary>
    /// 默认转换设置
    /// <para>日期：yyyy-MM-dd HH:mm:ss</para>
    /// <para>null：直接忽略</para>
    /// <para>属性：驼峰命名法</para>
    /// </summary>
    public static JsonSerializerSettings DefaultSettings => new()
    {
      //日期类型默认格式化处理
      DateFormatHandling = DateFormatHandling.MicrosoftDateFormat,
      DateFormatString = "yyyy-MM-dd HH:mm:ss.ffffff",
      NullValueHandling = NullValueHandling.Ignore,
      ContractResolver = new CamelCasePropertyNamesContractResolver(),
      ReferenceLoopHandling = ReferenceLoopHandling.Ignore
    };

    /// <summary>
    /// 序列化对象到Json格式的字符串
    /// </summary>
    /// <param name="obj">任意一个对象</param>
    /// <param name="format">指定 JsonTextWriter 的格式设置选项</param>
    /// <param name="setting">序列化设置。如果为null，则使用默认设置</param>
    /// <param name="code">操作标识</param>
    /// <returns>标准的Json格式的字符串</returns>
    public static OperateResult<string> ToJson(this object obj, Newtonsoft.Json.Formatting format = Newtonsoft.Json.Formatting.None, JsonSerializerSettings? setting = default, int code = 0)
    {
      if (obj == null)
      {
        return OperateResult<string>.Failed(message: "序列化对象不能为null", code);
      }

      try
      {
        return OperateResult<string>.Succeeded(JsonConvert.SerializeObject(value: obj, formatting: format, settings: setting ?? DefaultSettings), code: code);
      }
      catch (Exception ex)
      {
        return OperateResult<string>.Failed(exception: ex);
      }
    }

    /// <summary>
    /// 反序列化Json字符串到指定类型的单个对象或对象集合
    /// <para>Json字符串形式应与T类型形式保持一致。如果Json是集合形式，则T类型也应该是集合形式，否则将转换失败</para>
    /// </summary>
    /// <typeparam name="T">反序列化对象的类型</typeparam>
    /// <param name="jsonObj">需要反序列化的Json对象字符串</param>
    /// <param name="setting">反序列化设置。如果为null，则使用默认设置</param>
    /// <param name="code">操作标识</param>
    /// <returns>如果转换失败，则返回T类型的默认值</returns>
    public static OperateResult<T> ToModel<T>(this string jsonObj, JsonSerializerSettings? setting = default, int code = 0)
    {
      if (string.IsNullOrWhiteSpace(value: jsonObj))
        return OperateResult<T>.Failed(message: "反序列化的JSON字符串不能为空", code);

      try
      {
        var data = JsonConvert.DeserializeObject<T>(value: jsonObj, settings: setting ?? DefaultSettings);
        if (data == null)
        {
          return OperateResult<T>.Failed(message: "序列化数据为空", code);
        }
        //如果数据类型一致，都是单个对象或对象集合
        return OperateResult<T>.Succeeded(data, code: code);
      }
      catch (Exception ex)
      {
        return OperateResult<T>.Failed(exception: ex, code);
      }
    }
  }
}
